﻿#include <cstdlib>
#include <iostream>
#include <sys/wait.h> // 仅在Unix-like系统上需要
#include<vector>
#include<cctype>
#include<string>
#include<algorithm>
#include<atomic>
#include<thread>
#include<chrono>
#include<fstream>
#include<filesystem>

namespace fs = std::filesystem;

std::atomic<bool>success{ false };

inline bool isPass(const char ch)
{
	return isprint(ch);
}

//密码   命令头部  命令尾部     最终输出目录    临时存储目录
void extract(const std::vector<std::string>& passwdVec, const std::string& head, const std::string& tailer, const std::string& outputDir, const std::string& tempDir)
{
	fs::path dir_path(tempDir);

	std::string command, cpStr{ "cd " + tempDir + ";cp -r * " + outputDir };
	command = "mkdir -p " + tempDir;
	system(command.c_str());
	command = "cd " + tempDir + ";rm -rf *";
	system(command.c_str());

	int result, exit_status;
	bool isCorrectFile{ false };
	for (auto& passward : passwdVec)
	{
		if (success.load())
			break;
		command = head + passward + tailer;
		result = system(command.c_str());
		if (result == -1)
			continue;
		else
		{
			exit_status = WEXITSTATUS(result);
			if (!exit_status)
			{
				try {
					isCorrectFile = false;
					for (const auto& entry : fs::recursive_directory_iterator(dir_path))
					{
						if (entry.is_regular_file() && entry.file_size())
						{
							isCorrectFile = true;
							break;
						}
					}
				}
				catch (const fs::filesystem_error& e)
				{
					continue;
				}
				if (isCorrectFile)
				{
					success.store(true);
					//保存密码到这个文件中
					std::ofstream(outputDir + "pass.txt", std::ios::trunc | std::ios::binary) << "";
					std::ofstream(outputDir + "pass.txt", std::ios::app | std::ios::binary) << passward << '\n';
					break;
				}
			}
		}
	}



}


int main()
{
	auto startTime{ std::chrono::high_resolution_clock::now() }, endTime{ std::chrono::high_resolution_clock::now() };

	std::vector<std::string>vec,
		vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15, vec16;
	char ch;
	std::size_t begin{}, end{};

	//maxLen为密码长度，根据需要调整这个
	int len{ 0 }, maxLen{ 3 }, i;

	//要解压的压缩包  只需要设置要解压的压缩包和解压后输出的路径即可，其他不用动
	std::string fileName{ "/home/download/test.zip" };
	//解压后输出的路径
	std::string outputDir{ "/home/download/test" };
	std::string outputDir1, outputDir2, outputDir3, outputDir4, outputDir5, outputDir6, outputDir7, outputDir8,
		outputDir9, outputDir10, outputDir11, outputDir12, outputDir13, outputDir14, outputDir15, outputDir16;
	std::string tailer1, tailer2, tailer3, tailer4, tailer5, tailer6, tailer7, tailer8, tailer9, tailer10, tailer11,
		tailer12, tailer13, tailer14, tailer15, tailer16;


	outputDir1 = outputDir + "1";
	tailer1 = "\" " + fileName + " -o" + outputDir1 + " -aoa";
	outputDir2 = outputDir + "2";
	tailer2 = "\" " + fileName + " -o" + outputDir2 + " -aoa";
	outputDir3 = outputDir + "3";
	tailer3 = "\" " + fileName + " -o" + outputDir3 + " -aoa";
	outputDir4 = outputDir + "4";
	tailer4 = "\" " + fileName + " -o" + outputDir4 + " -aoa";
	outputDir5 = outputDir + "5";
	tailer5 = "\" " + fileName + " -o" + outputDir5 + " -aoa";
	outputDir6 = outputDir + "6";
	tailer6 = "\" " + fileName + " -o" + outputDir6 + " -aoa";
	outputDir7 = outputDir + "7";
	tailer7 = "\" " + fileName + " -o" + outputDir7 + " -aoa";
	outputDir8 = outputDir + "8";
	tailer8 = "\" " + fileName + " -o" + outputDir8 + " -aoa";
	outputDir9 = outputDir + "9";
	tailer9 = "\" " + fileName + " -o" + outputDir9 + " -aoa";
	outputDir10 = outputDir + "10";
	tailer10 = "\" " + fileName + " -o" + outputDir10 + " -aoa";
	outputDir11 = outputDir + "11";
	tailer11 = "\" " + fileName + " -o" + outputDir11 + " -aoa";
	outputDir12 = outputDir + "12";
	tailer12 = "\" " + fileName + " -o" + outputDir12 + " -aoa";
	outputDir13 = outputDir + "13";
	tailer13 = "\" " + fileName + " -o" + outputDir13 + " -aoa";
	outputDir14 = outputDir + "14";
	tailer14 = "\" " + fileName + " -o" + outputDir14 + " -aoa";
	outputDir15 = outputDir + "15";
	tailer15 = "\" " + fileName + " -o" + outputDir15 + " -aoa";
	outputDir16 = outputDir + "16";
	tailer16 = "\" " + fileName + " -o" + outputDir16 + " -aoa";


	std::string command, head{ "7z x -p\"" }, tailer{ "\" /home/download/test.zip -o/home/download/test" };
	char buf[100]{};
	char* pos, *writePos;
	int result, exit_status;



	for (ch = 0; ch != -128; ++ch)
	{
		if (isPass(ch))
			vec.emplace_back(std::string(1, ch));
	}


	begin = 0, end = vec.size();

	while (++len != maxLen)
	{

		for (i = begin; i != end; ++i)
		{
			pos = buf;
			std::copy(vec[i].cbegin(), vec[i].cend(), pos);
			pos += vec[i].size();
			writePos = pos;
			for (ch = 0; ch != -128; ++ch)
			{
				if (isPass(ch))
				{
					*writePos++ = ch;
					*writePos++ = 0;
					vec.emplace_back(buf);
					writePos = pos;
				}
			}
		}

		begin = end, end = vec.size();
	}

	command = "cd " + outputDir + ";rm -rf *";
	system(command.c_str());

	i = -1;
	for (auto& pass : vec)
	{
		switch (++i % 16)
		{
		case 0:
			vec1.emplace_back(pass);
			break;
		case 1:
			vec2.emplace_back(pass);
			break;
		case 2:
			vec3.emplace_back(pass);
			break;
		case 3:
			vec4.emplace_back(pass);
			break;
		case 4:
			vec5.emplace_back(pass);
			break;
		case 5:
			vec6.emplace_back(pass);
			break;
		case 6:
			vec7.emplace_back(pass);
			break;
		case 7:
			vec8.emplace_back(pass);
			break;
		case 8:
			vec9.emplace_back(pass);
			break;
		case 9:
			vec10.emplace_back(pass);
			break;
		case 10:
			vec11.emplace_back(pass);
			break;
		case 11:
			vec12.emplace_back(pass);
			break;
		case 12:
			vec13.emplace_back(pass);
			break;
		case 13:
			vec14.emplace_back(pass);
			break;
		case 14:
			vec15.emplace_back(pass);
			break;
		case 15:
			vec16.emplace_back(pass);
			break;
		default:

			break;
		}
	}

	vec.clear();
	vec = std::vector<std::string>();


	std::thread t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16;

	t1 = std::thread(extract, vec1, head, tailer1, outputDir, outputDir1);
	t2 = std::thread(extract, vec2, head, tailer2, outputDir, outputDir2);
	t3 = std::thread(extract, vec3, head, tailer3, outputDir, outputDir3);
	t4 = std::thread(extract, vec4, head, tailer4, outputDir, outputDir4);
	t5 = std::thread(extract, vec5, head, tailer5, outputDir, outputDir5);
	t6 = std::thread(extract, vec6, head, tailer6, outputDir, outputDir6);
	t7 = std::thread(extract, vec7, head, tailer7, outputDir, outputDir7);
	t8 = std::thread(extract, vec8, head, tailer8, outputDir, outputDir8);
	t9 = std::thread(extract, vec9, head, tailer9, outputDir, outputDir9);
	t10 = std::thread(extract, vec10, head, tailer10, outputDir, outputDir10);
	t11 = std::thread(extract, vec11, head, tailer11, outputDir, outputDir11);
	t12 = std::thread(extract, vec12, head, tailer12, outputDir, outputDir12);
	t13 = std::thread(extract, vec13, head, tailer13, outputDir, outputDir13);
	t14 = std::thread(extract, vec14, head, tailer14, outputDir, outputDir14);
	t15 = std::thread(extract, vec15, head, tailer15, outputDir, outputDir15);
	t16 = std::thread(extract, vec16, head, tailer16, outputDir, outputDir16);

	t1.detach();
	t2.detach();
	t3.detach();
	t4.detach();
	t5.detach();
	t6.detach();
	t7.detach();
	t8.detach();
	t9.detach();
	t10.detach();
	t11.detach();
	t12.detach();
	t13.detach();
	t14.detach();
	t15.detach();
	t16.detach();


	while (!success.load())
	{
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}

	endTime = std::chrono::high_resolution_clock::now();


	




	return 0;
}